#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>


#include <cerrno>
#include <iostream>
#include <cstring>
#include <unistd.h>

void Usage(const std::string& process)
{
    std::cout<<"Usage:"<<process<<" server_ip server_port\n";
}

int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        return 1;
    }
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);

    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock<0)
    {
        std::cerr<<"socket error:"<<strerror(errno)<<std::endl;
    }
    std::cout<<"create socket success , sock is:"<<sock<<"\n";
    //客户端需要 bind，但事实发送数据时bind，但是不显示bind，且一般在发送的时候隐式bind，不行甩开程序员来bind
    //server的端口不可改变，但是client时随机端口
    //为什么客户算需要随即呢？因为客户端十分多，如果占用就会出现问题

    //填充server信息
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(server_port);
    server.sin_addr.s_addr = inet_addr(server_ip.c_str()); 

    while(1)
    {
        std::string inbuffer; 
        std::cout<<"Please Enter\n";
        std::getline(std::cin,inbuffer);


        //发消息给server
        ssize_t n =  sendto(sock,inbuffer.c_str(),inbuffer.size(),0,(struct sockaddr*)&server,sizeof(server));
        if(n>0)
        {
            //sent success
            char buffer[1024] = {0};

            //因为recv会接受发送方的一些属性，所以我们需要一个接受，但是CLient是已经有了
            //可以暂时不管
            //为了防止传输空指针出现没必要的错误
            //还是传入参数
            struct sockaddr_in  temp;
            socklen_t len = sizeof(temp);
            ssize_t re_n =  recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&temp,&len);

            if(re_n>0)
            {
                std::cout<<buffer<<"\n";
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }

    }
    close(sock);
    return 0;
}
